package modelo.dominio;

import java.io.Serializable;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.text.SimpleDateFormat;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

@Entity
@Table(name ="Locacao")
public class Locacao implements Serializable {
	
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(unique=true, nullable=false)
	private int idLocacao;
	
	@Column(nullable=false)
	private long quilometragemSaida;
	
	@Column
	private long quilometragemEntrada;
	
	@Column(nullable=false)
	@Temporal(TemporalType.DATE)
	private Calendar dataSaida;
	
	@Column
	@Temporal(TemporalType.DATE)
	private Calendar dataDevolucao;
	
	@Column
	private double valorLocacao;
	
	@Column
	private int previsaoDias;
	
	@Column
	private boolean finalizada;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="idTipoLocacao")	
	@Fetch(FetchMode.JOIN)
	private TipoLocacao tipoLocacao;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="cnh")
	@Fetch(FetchMode.JOIN)
	private Motorista motorista;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="cpf")
	@Fetch(FetchMode.JOIN)
	private Cliente cliente;
	
	@ManyToOne(fetch=FetchType.EAGER)
	@JoinColumn(name="placa")
	@Fetch(FetchMode.JOIN)
	private Veiculo veiculo;
	
	public Locacao(){
		this.dataSaida = new GregorianCalendar();
	}
	
	public Locacao(Cliente cliente){
		this.cliente = cliente;
	}
	
	public Locacao(Veiculo veiculo){
		this.veiculo = veiculo;
	}
	
	public Locacao(long quilometragemSaida, int previsaoDias){
		this();
		this.quilometragemSaida = quilometragemSaida;
		this.previsaoDias = previsaoDias;
		this.finalizada = false;		// true = concluído
	}
	
	public Locacao(long quilometragemSaida, int previsaoDias,
		TipoLocacao tipoLocacao, Motorista motorista, Cliente cliente, Veiculo veiculo){
		this(quilometragemSaida, previsaoDias);
		this.tipoLocacao = tipoLocacao;
		this.motorista = motorista;
		this.cliente = cliente;
		this.veiculo = veiculo;
	}
	
	public Locacao(int idLocacao, long quilometragemSaida, long quilometragemEntrada, Calendar dataSaida,
		Calendar dataDevolucao, double valorLocacao, int previsaoDias, boolean finalizada,
		TipoLocacao tipoLocacao, Motorista motorista, Cliente cliente, Veiculo veiculo){
		this.idLocacao = idLocacao;
		this.quilometragemSaida = quilometragemSaida;
		this.quilometragemEntrada = quilometragemEntrada;
		this.dataSaida = dataSaida;
		this.dataDevolucao = dataDevolucao;
		this.valorLocacao = valorLocacao;
		this.previsaoDias = previsaoDias;
		this.finalizada = finalizada;
		this.tipoLocacao = tipoLocacao;
		this.motorista = motorista;
		this.cliente = cliente;
		this.veiculo = veiculo;
	}
	
	public int getIdLocacao() {
		return this.idLocacao;
	}
	
	public long getQuilometragemSaida() {
		return this.quilometragemSaida;
	}
	
	public long getQuilometragemEntrada() {
		return this.quilometragemEntrada;
	}
	
	public Calendar getDataSaida() {
		return this.dataSaida;
	}

	public Calendar getDataDevolucao() {
		return this.dataDevolucao;
	}
	
	public Double getValorLocacao() {
		return this.valorLocacao;
	}
	
	public int getPrevisaoDias() {
		return this.previsaoDias;
	}
	
	public boolean isFinalizada() {
		return this.finalizada;
	}
	
	public TipoLocacao getTipoLocacao() {
		return this.tipoLocacao;
	}

	public Motorista getMotorista() {
		return this.motorista;
	}
	
	public Cliente getCliente() {
		return this.cliente;
	}

	public Veiculo getVeiculo() {
		return this.veiculo;
	}
	
	public void setIdLocacao(int idLocacao) {
		this.idLocacao = idLocacao;
	}
	
	public void setQuilomentragemSaida(long quilometragemSaida){
		this.quilometragemSaida = quilometragemSaida;
	}
	
	public void setQuilometragemEntrada(long quilometragemEntrada){
		this.quilometragemEntrada = quilometragemEntrada;
	}
	
	public void setDataDevolucao(GregorianCalendar dataDevolucao) {
		this.dataDevolucao = dataDevolucao;
	}

	public void setValorLocacao(double valorLocacao){
		this.valorLocacao = valorLocacao;
	}
	
	public void setPrevisaoDias(int previsaoDias) {
		this.previsaoDias = previsaoDias;
	}

	public void setFinalizada(boolean finalizada) {
		this.finalizada = finalizada;
	}
	
	public void setTipoLocacao(TipoLocacao tipoLocacao){
		this.tipoLocacao = tipoLocacao;
	}
	
	public void setMotorista(Motorista motorista){
		this.motorista = motorista;
	}
	
	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}

	public void setVeiculo(Veiculo veiculo) {
		this.veiculo = veiculo;
	}
	
	public void calcularDataDevolucao(){
		GregorianCalendar devolucao = new GregorianCalendar();
		long saida = this.dataSaida.getTimeInMillis();
		long dif = 86400 * this.previsaoDias;
		devolucao.setTimeInMillis(saida + dif * 1000);
		this.setDataDevolucao(devolucao);
	}

	
	public double calcularValorLocacao(){
		double taxaBase, precoPorKm, precoDiaria, valor;
		double percentual = this.getVeiculo().getTipoVeiculo().getPercentual();
		long km;
		valor = 0;
		precoDiaria = this.getTipoLocacao().getPrecoDiaria();
		/* Cálculo do valor da locação por quilometragem */
		if (this.getTipoLocacao().getIdTipoLocacao() == 1){
			km = this.getQuilometragemEntrada() - this.getQuilometragemSaida();
			taxaBase = this.getTipoLocacao().getTaxaBase() * percentual;
			precoPorKm = this.getTipoLocacao().getPrecoPorKm() * percentual;
			valor = taxaBase + (precoPorKm * km);
		}
		/* Cálculo do valor da locação por diária */
		else if (this.getTipoLocacao().getIdTipoLocacao() == 2){
			valor = this.getPrevisaoDias() * precoDiaria * percentual;
		}
		this.setValorLocacao(valor);
		return this.valorLocacao;
	}
	
	@Override
	public String toString(){
		SimpleDateFormat dateFormat = new SimpleDateFormat();
		dateFormat.applyPattern("dd/MM/yyyy");
		return "ID: " + this.idLocacao + "\nTipo: " + this.tipoLocacao.getIdTipoLocacao() +
		"\nValor: R$ " + this.valorLocacao + "\nPrevisão de dias: " + this.previsaoDias +
		"\nData saída: " + dateFormat.format(this.dataSaida.getTime()) + 
		//"\nData devolução: " + dateFormat.format(this.dataDevolucao.getTime()) + 
		"\nVeículo: " + this.getVeiculo().getPlaca() + 
		"\nQuilometragem de saída: " + this.quilometragemSaida + 
		"\nQuilometragem de entrada: " + this.quilometragemEntrada + 
		"\nConcluída: " + this.finalizada + "\n";
	}
	
}